home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / fsattach / RCS / misc.c,v < prev   
Encoding:
Text File  |  1991-01-13  |  32.2 KB  |  1,380 lines

  1. head     1.10;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.10
  10. date     91.01.12.16.55.15;  author jhh;  state Exp;
  11. branches ;
  12. next     1.9;
  13.  
  14. 1.9
  15. date     90.10.22.09.28.52;  author mendel;  state Exp;
  16. branches ;
  17. next     1.8;
  18.  
  19. 1.8
  20. date     90.08.02.00.21.38;  author jhh;  state Exp;
  21. branches ;
  22. next     1.7;
  23.  
  24. 1.7
  25. date     90.02.14.13.59.55;  author jhh;  state Exp;
  26. branches ;
  27. next     1.6;
  28.  
  29. 1.6
  30. date     89.12.14.16.27.36;  author jhh;  state Exp;
  31. branches ;
  32. next     1.5;
  33.  
  34. 1.5
  35. date     89.10.25.18.06.21;  author jhh;  state Exp;
  36. branches ;
  37. next     1.4;
  38.  
  39. 1.4
  40. date     89.06.19.14.21.18;  author jhh;  state Exp;
  41. branches ;
  42. next     1.3;
  43.  
  44. 1.3
  45. date     89.06.07.22.14.28;  author jhh;  state Exp;
  46. branches ;
  47. next     1.2;
  48.  
  49. 1.2
  50. date     89.04.10.11.12.18;  author jhh;  state Exp;
  51. branches ;
  52. next     1.1;
  53.  
  54. 1.1
  55. date     89.03.06.12.58.50;  author jhh;  state Exp;
  56. branches ;
  57. next     ;
  58.  
  59.  
  60. desc
  61. @@
  62.  
  63.  
  64. 1.10
  65. log
  66. @bug fix for copying output into .fsc files
  67. @
  68. text
  69. @/* 
  70.  * misc.c --
  71.  *
  72.  *    Miscellaneous utility procedures for fsattach.
  73.  *
  74.  * Copyright 1989 Regents of the University of California
  75.  * Permission to use, copy, modify, and distribute this
  76.  * software and its documentation for any purpose and without
  77.  * fee is hereby granted, provided that the above copyright
  78.  * notice appear in all copies.  The University of California
  79.  * makes no representations about the suitability of this
  80.  * software for any purpose.  It is provided "as is" without
  81.  * express or implied warranty.
  82.  */
  83.  
  84. #ifndef lint
  85. static char rcsid[] = "$Header: /sprite/src/admin/fsattach/RCS/misc.c,v 1.9 90/10/22 09:28:52 mendel Exp Locker: jhh $ SPRITE (Berkeley)";
  86. #endif /* not lint */
  87.  
  88. #include "fsattach.h"
  89.  
  90.  
  91. /*
  92.  *----------------------------------------------------------------------
  93.  *
  94.  * ParseMount --
  95.  *
  96.  *    Parses the mount information in the file and fills in the mount
  97.  *    table. 
  98.  *
  99.  * Results:
  100.  *    SUCCESS if the information was parsed ok, FAILURE otherwise.
  101.  *
  102.  * Side effects:
  103.  *    *countPtr contains the size of the mount table.
  104.  *
  105.  *
  106.  *----------------------------------------------------------------------
  107.  */
  108.  
  109. ReturnStatus
  110. ParseMount(mountFile, countPtr)
  111.     char    *mountFile;        /* file containing mount info */
  112.     int        *countPtr;        /* Ptr to size of mount table */
  113. {
  114.     static char     source[MAX_FIELD_LENGTH];
  115.     static char     string[MAX_LINE_LENGTH];
  116.     static char     dest[MAX_FIELD_LENGTH];
  117.     static char     command[MAX_FIELD_LENGTH];
  118.     static char     readFlag[MAX_FIELD_LENGTH];
  119.     static char     arg[MAX_FIELD_LENGTH];
  120.     static char     group[MAX_FIELD_LENGTH];
  121.     char         exportString[MAX_FIELD_LENGTH];
  122.     int         n;
  123.     Boolean        export;
  124.     char         *eof;
  125.     int         line;
  126.     int            index;
  127.     Boolean        readonly;
  128.     FILE        *stream;
  129.     ArgInfo        *argTable = NULL;
  130.     int            argTableSize;
  131.     int            argTableSizeIncrement = 5;
  132.     int            argCount;
  133.     ArgInfo        *argInfoPtr = NULL;
  134.     int            argIndex;
  135.     int            i;
  136.     int            j;
  137.     ReturnStatus    status;
  138.     ArgHeader        *argHeader;
  139.  
  140.     status = SUCCESS;
  141.     stream = fopen(mountFile, "r");
  142.     if (stream == (FILE *)NULL) {
  143.     (void) fprintf(stderr, "%s: can't open \"%s\", ", progName, mountFile);
  144.     perror("");
  145.     return FAILURE;
  146.     }
  147.     line = 0;
  148.     index = 0;
  149.     argCount = 0;
  150.     argTableSize = 0;
  151.     if (verbose) {
  152.     fprintf(stderr,"Parsing mount file %s.\n", mountFile);
  153.     }
  154.     for (eof = fgets(string, MAX_LINE_LENGTH, stream);
  155.      eof != NULL;
  156.      eof = fgets(string, MAX_LINE_LENGTH, stream)) {
  157.  
  158.     line++;
  159.     n = sscanf(string, " %256s", command);
  160.     if (n < 1 || *command == '#') {
  161.         continue;
  162.     }
  163.     if (index >= mountTableSize) {
  164.         mountTableSize += mountTableSizeIncrement;
  165.         mountTable = (MountInfo *) realloc(mountTable, mountTableSize);
  166.         if (mountTable == NULL) {
  167.         (void) fprintf(stderr,"%s: Out of memory.\n");
  168.         (void) exit(HARDERROR);
  169.         }
  170.     }
  171.     if (!strcasecmp("Attach", command)) {
  172.         n = sscanf(string, " %*s %256s %256s %256s %256s %256s", dest, 
  173.                source, group, exportString, readFlag);
  174.         if (n != 5) {
  175.         (void) fprintf(stderr, 
  176.                    "Garbled input at line %d of %s: \"%s\"\n", 
  177.                    line, mountFile, string);
  178.         continue;
  179.         }
  180.         export = TRUE;
  181.         if (!strcasecmp("export", exportString)) {
  182.         export = TRUE;
  183.         } else if (!strcasecmp("local", exportString)) {
  184.         export = FALSE;
  185.         } else {
  186.         (void) fprintf(stderr, "Bad export value at line %d: \"%s\"\n", 
  187.                    line, exportString);
  188.         continue;
  189.         }
  190.         for (i = 0; i < numGroups; i++) {
  191.         if (!strcmp(groupInfo[i].name, group)) {
  192.             break;
  193.         }
  194.         }
  195.         if (i == numGroups) {
  196.         if (i >= groupInfoSize) {
  197.             groupInfoSize += groupInfoSizeIncrement;
  198.             groupInfo = (GroupInfo *) realloc(groupInfo, groupInfoSize);
  199.             if (groupInfoSize == NULL) {
  200.             (void) fprintf(stderr,"%s: Out of memory.\n");
  201.             (void) exit(HARDERROR);
  202.             }
  203.         }
  204.         numGroups++;
  205.         strcpy(groupInfo[i].name, group);
  206.         }
  207.         mountTable[index].group = i;
  208.         if (!strcasecmp("r", readFlag)) {
  209.         readonly = TRUE;
  210.         } else  if (!strcasecmp("rw", readFlag)) {
  211.         readonly = FALSE;
  212.         } else {
  213.         (void) fprintf(stderr, 
  214.                    "Bad read/write value at line %d: \"%s\"\n",
  215.                    line, readFlag);
  216.         continue;
  217.         }
  218.         if (verbose) {
  219.         (void) printf("%-20s %-10s %-10s %-10s %-2s\n", dest, source, 
  220.                       group, exportString, readFlag);
  221.         }
  222.         mountTable[index].export = export;
  223.         mountTable[index].readonly = readonly;
  224.         mountTable[index].device = TRUE;
  225.         mountTable[index].doCheck = TRUE;
  226.         mountTable[index].checked = FALSE;
  227.         (void) strcpy(mountTable[index].source, source);
  228.         (void) strcpy(mountTable[index].dest, dest);
  229.         List_Init(&mountTable[index].argInfo.argList);
  230.         index++;
  231.     } else if (!strcasecmp("Export", command)) {
  232.         n = sscanf(string, " %*s %256s %256s", dest, source);
  233.         if (n != 2) {
  234.         (void) fprintf(stderr, 
  235.                    "Garbled input at line %d of %s: \"%s\"\n", 
  236.                    line, mountFile, string);
  237.         continue;
  238.         }
  239.         if (verbose) {
  240.         printf("%-20s %-10s\n", dest, source);
  241.         }
  242.         mountTable[index].export = TRUE;
  243.         mountTable[index].readonly = FALSE;
  244.         mountTable[index].device = FALSE;
  245.         mountTable[index].doCheck = FALSE;
  246.         mountTable[index].checked = FALSE;
  247.         (void) strcpy(mountTable[index].source, source);
  248.         (void) strcpy(mountTable[index].dest, dest);
  249.         List_Init(&mountTable[index].argInfo.argList);
  250.         index++;
  251.     } else {
  252.         n = sscanf(string, " %256s", source);
  253.         if (n != 1) {
  254.         (void) fprintf(stderr, 
  255.                    "Garbled input at line %d of %s: \"%s\"\n", 
  256.                    line, mountFile, string);
  257.         continue;
  258.         }
  259.         if (argCount >= argTableSize) {
  260.         argTableSize += argTableSizeIncrement;
  261.         if (argCount == 0) {
  262.             Alloc(argTable, ArgInfo, argTableSize, "argTable");
  263.         } else {
  264.             argTable = (ArgInfo *) realloc(argTable, argTableSize);
  265.         }
  266.         if (argTable == NULL) {
  267.             (void) fprintf(stderr,"%s: Out of memory.\n");
  268.             (void) exit(HARDERROR);
  269.         }
  270.         }
  271.         i = 0;
  272.         Alloc(argInfoPtr, ArgInfo, 1, "argInfoPtr");
  273.         List_Init(&argInfoPtr->argList);
  274.         argInfoPtr->line = line;
  275.         strcpy(argInfoPtr->source, source);
  276.         for (argIndex = strspn(string, " \t"); 
  277.          string[argIndex] != '\0';
  278.          argIndex += strcspn(&string[argIndex], " \t\n"),
  279.          argIndex += strspn(&string[argIndex], " \t\n"), 
  280.          i++) {
  281.  
  282.          if (i < 1) {
  283.              continue;
  284.          }
  285.          if (sscanf(&string[argIndex], " %s", arg) == 0) {
  286.              break;
  287.          }
  288.          Alloc(argHeader, ArgHeader, 1, "argHeader");
  289.          List_InitElement((List_Links *) argHeader);
  290.          Alloc(argHeader->arg, char, strlen(arg) + 1, "arg");
  291.          strcpy(argHeader->arg, arg);
  292.          List_Insert((List_Links *) argHeader, 
  293.              LIST_BEFORE((List_Links *) &argInfoPtr->argList));
  294.          }
  295.         if (strcasecmp(source, "all")) {
  296.         for (i = 0; i < index; i++) {
  297.              if (!strcmp(mountTable[i].source, source)) {
  298.              MergeList(&argInfoPtr->argList, 
  299.                  &mountTable[i].argInfo.argList);
  300.              break;
  301.              }
  302.          }
  303.          if (i == index) {
  304.              argTable[argCount] = *argInfoPtr;
  305.              List_Init(&argTable[argCount].argList);
  306.              AddList(&argInfoPtr->argList, 
  307.              &argTable[argCount].argList);
  308.              free(argInfoPtr);
  309.              argCount++;
  310.          }
  311.          } else {
  312.          argTable[argCount] = *argInfoPtr;
  313.          List_Init(&argTable[argCount].argList);
  314.          AddList(&argInfoPtr->argList, 
  315.              &argTable[argCount].argList);
  316.          free(argInfoPtr);
  317.          argCount++;
  318.          }
  319.     }   
  320.     }
  321.     for (i = 0; i < argCount; i++) {
  322.     if (!strcasecmp(argTable[i].source, "all")) {
  323.         for (j = 0; j < index; j++) {
  324.         if (mountTable[j].device == TRUE) {
  325.             MergeList(&argTable[i].argList, 
  326.             &mountTable[j].argInfo.argList);
  327.             strcpy(mountTable[j].argInfo.source, argTable[i].source);
  328.             mountTable[j].argInfo.line = argTable[i].line;
  329.         }
  330.         }
  331.         DeleteList(&argTable[i].argList);
  332.     } else {
  333.         for (j = 0; j < index; j++) {
  334.          if (!strcmp(argTable[i].source, mountTable[j].source)) {
  335.              MergeList(&argTable[i].argList, 
  336.              &mountTable[j].argInfo.argList);
  337.             strcpy(mountTable[i].argInfo.source, 
  338.                 argTable[i].source);
  339.             mountTable[i].argInfo.line = argTable[i].line;
  340.              break;
  341.          }
  342.          }
  343.          if (j == index) {
  344.          fprintf(stderr, "Device %s not found at line %d\n", 
  345.              argTable[i].source, argTable[i].line);
  346.          status = FAILURE;
  347.          }
  348.      }
  349.      }
  350.     if (argTable != NULL) {
  351.     free(argTable);
  352.     }
  353.     fclose(stream);
  354.     *countPtr = index;
  355.     return status;
  356. }
  357.  
  358. /*
  359.  *----------------------------------------------------------------------
  360.  *
  361.  * MergeList --
  362.  *
  363.  *    Merge the src list into the dest list without modifying the source
  364.  *    list.
  365.  *
  366.  * Results:
  367.  *    None.
  368.  *
  369.  * Side effects:
  370.  *    Memory is allocated and the dest list is modified.
  371.  *
  372.  *----------------------------------------------------------------------
  373.  */
  374.  
  375. void
  376. MergeList(srcListPtr, destListPtr)
  377.     ArgHeader *srcListPtr;        /* source list */
  378.     ArgHeader *destListPtr;        /* destination list */
  379.  
  380. {
  381.     List_Links    *itemPtr;
  382.     List_Links    *newPtr;
  383.  
  384.     LIST_FORALL((List_Links *) srcListPtr, itemPtr) {
  385.     Alloc((ArgHeader *) newPtr, ArgHeader, 1, "newPtr");
  386.     *((ArgHeader *) newPtr) = *((ArgHeader *) itemPtr);
  387.     List_Insert(newPtr, LIST_ATREAR((List_Links *) destListPtr));
  388.     }
  389. }
  390.  
  391. /*
  392.  *----------------------------------------------------------------------
  393.  *
  394.  * AddList --
  395.  *
  396.  *    Adds the src list to the dest list. 
  397.  *
  398.  * Results:
  399.  *    None.
  400.  *
  401.  * Side effects:
  402.  *    The dest list is modified. 
  403.  *
  404.  *----------------------------------------------------------------------
  405.  */
  406.  
  407. void
  408. AddList(srcListPtr, destListPtr)
  409.     ArgHeader *srcListPtr;        /* source list */
  410.     ArgHeader *destListPtr;        /* destination list */
  411.  
  412. {
  413.     List_Links    *itemPtr;
  414.     List_Links    *tempPtr;
  415.  
  416.     itemPtr = List_First((List_Links *) srcListPtr);
  417.     while (!List_IsAtEnd((List_Links *) srcListPtr, itemPtr)) {
  418.     tempPtr = itemPtr;
  419.     itemPtr = List_Next(itemPtr);
  420.     List_Remove(tempPtr);
  421.     List_Insert(tempPtr, LIST_ATREAR((List_Links *) destListPtr));
  422.     }
  423. }
  424.  
  425. /*
  426.  *----------------------------------------------------------------------
  427.  *
  428.  * DeleteList --
  429.  *
  430.  *    Frees a list.
  431.  *
  432.  * Results:
  433.  *    None.
  434.  *
  435.  * Side effects:
  436.  *    The list is freed.
  437.  *
  438.  *----------------------------------------------------------------------
  439.  */
  440.  
  441. void
  442. DeleteList(listPtr)
  443.     ArgHeader    *listPtr;    /* list to be freed */
  444. {
  445.     List_Links    *itemPtr;
  446.     List_Links    *tempPtr;
  447.  
  448.     itemPtr = List_First((List_Links *) listPtr);
  449.     while (!List_IsAtEnd((List_Links *) listPtr, itemPtr)) {
  450.     tempPtr = itemPtr;
  451.     itemPtr = List_Next(itemPtr);
  452.     List_Remove(tempPtr);
  453.     free(tempPtr);
  454.     }
  455. }
  456.  
  457.  
  458. /*
  459.  *----------------------------------------------------------------------
  460.  *
  461.  * MoveOutput --
  462.  *
  463.  *    Fscheck stores its output in a special
  464.  *    preallocated file. We want to copy the information out of that
  465.  *    file into the standard fscheck output file, and then zero out
  466.  *    the special file.
  467.  *
  468.  * Results:
  469.  *    None.
  470.  *
  471.  * Side effects:
  472.  *    The root output is appended to the output file and the special
  473.  *    output file is filled with null characters.
  474.  *
  475.  *----------------------------------------------------------------------
  476.  */
  477.  
  478. void
  479. MoveOutput(mountCount)
  480.     int        mountCount;
  481. {
  482.     FILE     *outputStream;
  483.     FILE    *tempStream;
  484.     char    outputFile[MAX_LINE_LENGTH];
  485.     char    inputFile[MAX_LINE_LENGTH];
  486.     int        bytesRead;
  487.     int        bytesWritten;
  488.     int        bytesToWrite;
  489.     char    buffer[1024];
  490.     int        i, mountIndex;
  491.     Boolean    done;
  492.     char    *hostName;
  493.  
  494.     if (verbose) {
  495.     printf("Moving output from fscheck.\n");
  496.     }
  497.     hostName = getenv("HOST");
  498.     for(mountIndex = 0; mountIndex < mountCount; mountIndex++) {
  499.     if (debug) {
  500.         printf("%d (%s): device = %s, status = %s\n", mountIndex, 
  501.         mountTable[mountIndex].source,
  502.         (mountTable[mountIndex].device == TRUE ? "true" : "false"),
  503.         (mountTable[mountIndex].status == CHILD_OK) ? "ok" : "not ok");
  504.     }
  505.     if (mountTable[mountIndex].checked == FALSE ||
  506.         mountTable[mountIndex].status != CHILD_OK ||
  507.         mountTable[mountIndex].device == FALSE) {
  508.         continue;
  509.     }
  510.     (void) sprintf(outputFile, "/hosts/%s/%s.fsc", hostName,
  511.         mountTable[mountIndex].source);
  512.     if (verbose) {
  513.         printf("Copying output from checking %s to %s.\n", 
  514.         mountTable[mountIndex].source, outputFile);
  515.     }
  516.     outputStream = fopen(outputFile, "a+");
  517.     if (outputStream == (FILE *)NULL) {
  518.         (void) fprintf(stderr, "%s: can't open \"%s\", ", progName, 
  519.             outputFile);
  520.         perror("");
  521.         return;
  522.     }
  523.     (void) sprintf(inputFile, "%s/%s", mountTable[mountIndex].dest,
  524.         tempOutputFile);
  525.     tempStream = fopen(inputFile,"r+");
  526.     if (tempStream == (FILE *)NULL) {
  527.         (void) fprintf(stderr, "%s: can't open \"%s\", ", progName,
  528.                inputFile);
  529.         perror("");
  530.         fclose(outputStream);
  531.         return;
  532.     }
  533.     bytesRead = fread(buffer, sizeof(char), 1024, tempStream);
  534.     done = FALSE;
  535.     while(bytesRead > 0 && !done) {
  536.         for (i = 0; i < bytesRead; i++) {
  537.         if ( buffer[i] == '\0') {
  538.             done = TRUE;
  539.             break;
  540.         }
  541.         }
  542.         bytesToWrite = i;
  543.         bytesWritten = fwrite(buffer, sizeof(char), bytesToWrite, 
  544.         outputStream);
  545.         if (bytesWritten < bytesToWrite) {
  546.         (void) fprintf(stderr, "%s: Unable to copy output to %s.\n",
  547.             progName, outputFile);
  548.         goto cleanup;
  549.         }
  550.         bytesRead = fread(buffer, sizeof(char), 1024, tempStream);
  551.     }
  552.     rewind(tempStream);
  553.     (void) bzero(buffer, 1024);
  554.     for (i = 0; i < tempOutputFileSize; i += bytesToWrite) {
  555.         bytesToWrite = min(1024, tempOutputFileSize - i);
  556.         bytesWritten = fwrite(buffer, sizeof(char), bytesToWrite, 
  557.                     tempStream);
  558.         if (bytesWritten != bytesToWrite) {
  559.         fprintf(stderr, "Only wrote %d bytes: ", bytesWritten);
  560.         perror("");
  561.         break;
  562.         }
  563.     }
  564. cleanup:
  565.     (void) fclose(outputStream);
  566.     (void) fclose(tempStream);
  567.     }
  568. }
  569.  
  570. /*
  571.  *----------------------------------------------------------------------
  572.  *
  573.  * PrintFscheckError --
  574.  *
  575.  *    Prints a meaningful description of fscheck's error codes.
  576.  *
  577.  * Results:
  578.  *    None.
  579.  *
  580.  * Side effects:
  581.  *    None.
  582.  *
  583.  *----------------------------------------------------------------------
  584.  */
  585.  
  586. void
  587. PrintFscheckError(code, mountPtr)
  588.     char    code;        /* error code from fscheck */
  589.     MountInfo    *mountPtr;    /* mount info for partition checked */
  590. {
  591.     static char *softerrors[] = {
  592.     "No errors",
  593.     "Correctable error",
  594.     "Exceeded heap limit",
  595.     "No reboot",
  596.     "Reboot",
  597.     };
  598.     static char *harderrors[] = {
  599.     "",
  600.     "Read of device failed",
  601.     "Write to device failed",
  602.     "Bad argument",
  603.     "Heap limit too small",
  604.     "Disk is full",
  605.     };
  606.     char *error;
  607.     int     index;
  608.  
  609.     index = (int) code;
  610.     if (index < 0) {
  611.     error = harderrors[-index];
  612.     } else { 
  613.     error = softerrors[index];
  614.     }
  615.     (void) fprintf(stderr, "Fscheck of %s returned (%d) : %s.\n", 
  616.            mountPtr->source, index, error);
  617. }
  618.  
  619. /*
  620.  *----------------------------------------------------------------------
  621.  *
  622.  * PreloadPrefixTable --
  623.  *
  624.  *    Load the prefix table with ourself as the server of all the
  625.  *     prefixes we export. That way we don't broadcast for them
  626.  *    while we check our disks.
  627.  *
  628.  * Results:
  629.  *    None.
  630.  *
  631.  * Side effects:
  632.  *    Exported prefixes are loaded into the prefix table.
  633.  *
  634.  *----------------------------------------------------------------------
  635.  */
  636.  
  637. void
  638. PreloadPrefixTable(spriteID, mountCount)
  639.     int    spriteID;        /* Our Sprite ID. */
  640.     int    mountCount;        /* Size of mount table. */
  641. {
  642.     int            i;
  643.     Fs_PrefixLoadInfo    loadInfo;
  644.     ReturnStatus    status;
  645.  
  646.     for (i = 0; i < mountCount; i++) {
  647.     if ((mountTable[i].export == TRUE) && 
  648.         (strcmp("/", mountTable[i].dest) != 0)) {
  649.         (void) strncpy(loadInfo.prefix, mountTable[i].dest,
  650.             FS_MAX_PATH_NAME_LENGTH);
  651.         loadInfo.serverID = spriteID;
  652.         if (printOnly || verbose) {
  653.         printf("Preloading prefix \"%s\"\n", loadInfo.prefix);
  654.         }
  655.         if (!printOnly) {
  656.         status = Fs_Command(FS_PREFIX_LOAD, sizeof(Fs_PrefixLoadInfo), 
  657.              &loadInfo);
  658.         if (status != SUCCESS) {
  659.             fprintf(stderr, "Couldn't load prefix \"%s\": %s.\n",
  660.                 mountTable[i].dest, Stat_GetMsg(status));
  661.         }
  662.         }
  663.     }
  664.     }
  665. }
  666.  
  667. /*
  668.  *----------------------------------------------------------------------
  669.  *
  670.  * GetAttachName --
  671.  *
  672.  *    Get the name of the prefix under which the filesystem was
  673.  *    attached.
  674.  *
  675.  * Results:
  676.  *    Name of the prefix.
  677.  *
  678.  * Side effects:
  679.  *    The disk is read.
  680.  *
  681.  *----------------------------------------------------------------------
  682.  */
  683.  
  684. char *
  685. GetAttachName(device)
  686.     char    *device;
  687. {
  688.     int            fd;
  689.     Disk_Label        *labelPtr;
  690.     Ofs_SummaryInfo    *summaryPtr;
  691.     char        *prefix;
  692.     ReturnStatus    status;
  693.  
  694.     fd = open(device, O_RDWR);
  695.     if (fd < 0) {
  696.     fprintf(stderr, "Could not open %s\n", device);
  697.     return NULL;
  698.     }
  699.     labelPtr = Disk_ReadLabel(fd);
  700.     if (labelPtr == NULL) {
  701.     fprintf(stderr, "Could not read label from %s\n", device);
  702.     return NULL;
  703.     }
  704.     summaryPtr = Disk_ReadSummaryInfo(fd, labelPtr);
  705.     if ( summaryPtr == NULL) {
  706.     fprintf(stderr, "Could not read summary info from %s\n", device);
  707.     return NULL;
  708.     }
  709.     prefix = summaryPtr->domainPrefix;
  710.     /*
  711.      * FIX THIS:  The following code to clear a bit in the summary sector
  712.      * is only needed for kernels prior to 1.070.  It can be removed
  713.      * once those kernels are gone.  JHH.
  714.      */
  715.     summaryPtr->flags &= ~OFS_DOMAIN_JUST_CHECKED;
  716.     status = Disk_WriteSummaryInfo(fd, labelPtr, summaryPtr);
  717.     if (status != SUCCESS) {
  718.     fprintf(stderr, "Could not write summary info to %s\n", device);
  719.     return NULL;
  720.     }
  721.     close(fd);
  722.     return prefix;
  723. }
  724.  
  725. @
  726.  
  727.  
  728. 1.9
  729. log
  730. @Changes for new OFS file systems names.
  731. @
  732. text
  733. @d17 1
  734. a17 1
  735. static char rcsid[] = "$Header: /sprite/src/admin/fsattach/RCS/misc.c,v 1.8 90/08/02 00:21:38 jhh Exp Locker: mendel $ SPRITE (Berkeley)";
  736. d422 1
  737. a422 1
  738.     int        i;
  739. d430 1
  740. a430 1
  741.     for(i = 0; i < mountCount; i++) {
  742. d432 4
  743. a435 4
  744.         printf("%d (%s): device = %s, status = %s\n", i, 
  745.         mountTable[i].source,
  746.         (mountTable[i].device == TRUE ? "true" : "false"),
  747.         (mountTable[i].status == CHILD_OK) ? "ok" : "not ok");
  748. d437 3
  749. a439 3
  750.     if (mountTable[i].checked == FALSE ||
  751.         mountTable[i].status != CHILD_OK ||
  752.         mountTable[i].device == FALSE) {
  753. d443 1
  754. a443 1
  755.         mountTable[i].source);
  756. d446 1
  757. a446 1
  758.         mountTable[i].source, outputFile);
  759. d455 2
  760. a456 1
  761.     (void) sprintf(inputFile, "%s/%s", mountTable[i].dest, tempOutputFile);
  762. @
  763.  
  764.  
  765. 1.8
  766. log
  767. @made it compatible with pre 1.070 kernels
  768. @
  769. text
  770. @d17 1
  771. a17 1
  772. static char rcsid[] = "$Header: /sprite/src/admin/fsattach/RCS/misc.c,v 1.7 90/02/14 13:59:55 jhh Exp $ SPRITE (Berkeley)";
  773. d621 1
  774. a621 1
  775.     Fsdm_SummaryInfo    *summaryPtr;
  776. d646 1
  777. a646 1
  778.     summaryPtr->flags &= ~FSDM_DOMAIN_JUST_CHECKED;
  779. @
  780.  
  781.  
  782. 1.7
  783. log
  784. @Uses groups instead of passes
  785. @
  786. text
  787. @d17 1
  788. a17 1
  789. static char rcsid[] = "$Header: /sprite/src/admin/fsattach/RCS/misc.c,v 1.6 89/12/14 16:27:36 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  790. a60 1
  791.     static Boolean    foundRoot = FALSE;
  792. a121 12
  793.         if (!strcasecmp(group, "root")) {
  794.         if (foundRoot) {
  795.             (void) fprintf(stderr, 
  796.            "Illegal group value at line %d: %s.\n", group);
  797.             fprintf(stderr, 
  798.         "Only root partition can be checked in the \"root\" group.\n");
  799.             continue;
  800.         }
  801.         strcpy(group,"root");
  802.         } else {
  803.         foundRoot = TRUE;
  804.         }
  805. d158 1
  806. d178 1
  807. d393 1
  808. a393 1
  809.  * MoveRootOutput --
  810. d395 1
  811. a395 1
  812.  *    Fscheck stores the output for the root partition in a special
  813. d411 2
  814. a412 2
  815. MoveRootOutput(device)
  816.     char        *device;    /* name of the root partition */
  817. d424 1
  818. a425 1
  819.     (void) sprintf(outputFile, "/hosts/%s/%s.fsc", getenv("HOST"), device);
  820. d427 1
  821. a427 1
  822.     printf("Copying root output to %s.\n", outputFile);
  823. d429 25
  824. a453 23
  825.     outputStream = fopen(outputFile, "a+");
  826.     if (outputStream == (FILE *)NULL) {
  827.     (void) fprintf(stderr, "%s: can't open \"%s\", ", progName, outputFile);
  828.     perror("");
  829.     return;
  830.     }
  831.     (void) sprintf(inputFile, "%s/%s", bootPrefix, rootTempOutputFile);
  832.     tempStream = fopen(inputFile,"r+");
  833.     if (tempStream == (FILE *)NULL) {
  834.     (void) fprintf(stderr, "%s: can't open \"%s\", ", progName,
  835.                inputFile);
  836.     perror("");
  837.     fclose(outputStream);
  838.     return;
  839.     }
  840.     bytesRead = fread(buffer, sizeof(char), 1024, tempStream);
  841.     done = FALSE;
  842.     while(bytesRead > 0 && !done) {
  843.     for (i = 0; i < bytesRead; i++) {
  844.         if ( buffer[i] == '\0') {
  845.         done = TRUE;
  846.         break;
  847.         }
  848. d455 8
  849. a462 6
  850.     bytesToWrite = i;
  851.     bytesWritten = fwrite(buffer, sizeof(char), bytesToWrite, outputStream);
  852.     if (bytesWritten < bytesToWrite) {
  853.         (void) fprintf(stderr, "%s: Unable to copy root output to %s.\n",
  854.             progName, outputFile);
  855.         goto cleanup;
  856. d465 29
  857. a493 10
  858.     }
  859.     rewind(tempStream);
  860.     (void) bzero(buffer, 1024);
  861.     for (i = 0; i < rootTempOutputFileSize; i += bytesToWrite) {
  862.     bytesToWrite = min(1024, rootTempOutputFileSize - i);
  863.     bytesWritten = fwrite(buffer, sizeof(char), bytesToWrite, tempStream);
  864.     if (bytesWritten != bytesToWrite) {
  865.         fprintf(stderr, "Only wrote %d bytes: ", bytesWritten);
  866.         perror("");
  867.         break;
  868. d495 3
  869. a498 3
  870. cleanup:
  871.     (void) fclose(outputStream);
  872.     (void) fclose(tempStream);
  873. d523 2
  874. a524 2
  875.     "",
  876.     "Generic soft error",
  877. d526 2
  878. a527 1
  879.     "Soft error and fix limit exceeded"
  880. d578 1
  881. a578 1
  882.     if ((mountTable[i].export == TRUE) && (mountTable[i].group != 0) && 
  883. d596 58
  884. @
  885.  
  886.  
  887. 1.6
  888. log
  889. @was opening /.fscheck.out, which is the wrong file on fileservers
  890. that do not boot standalone.  Now opens /bootTmp/.fscheck.out
  891. @
  892. text
  893. @d17 1
  894. a17 1
  895. static char rcsid[] = "$Header: /sprite/src/admin/fsattach/RCS/misc.c,v 1.5 89/10/25 18:06:21 jhh Exp $ SPRITE (Berkeley)";
  896. d52 1
  897. a52 1
  898.     int             pass;
  899. d62 1
  900. a62 1
  901.     ArgInfo        *argTable;
  902. d66 1
  903. a66 1
  904.     ArgInfo        *argInfoPtr;
  905. a79 1
  906.     maxPass = 0;
  907. d105 2
  908. a106 2
  909.         n = sscanf(string, " %*s %256s %256s %d %256s %256s", dest, 
  910.                source, &pass, exportString, readFlag);
  911. d123 1
  912. a123 13
  913.         if (pass < 0) {
  914.         (void) fprintf(stderr, "Bad pass value at line %d: \"%d\"\n", 
  915.                    line, pass);
  916.         continue;
  917.         }
  918.         if (pass > MAX_PASS) {
  919.         (void) fprintf(stderr, 
  920.                    "Pass value %d too large at line %d: \"%d\"\n",
  921.                    line, pass);
  922.         (void) fprintf(stderr, "Reset to %d.\n", MAX_PASS);
  923.         pass = MAX_PASS;
  924.         }
  925.         if (pass == 0) {
  926. d126 3
  927. a128 2
  928.                        "Illegal pass value at line %d: %s.\n",
  929.                    line, "Only root can be checked on pass 0");
  930. d131 1
  931. d135 16
  932. a150 2
  933.         if (pass > maxPass) {
  934.         maxPass = pass;
  935. d152 1
  936. d164 2
  937. a165 2
  938.         (void) printf("%-20s %-10s %2d %-10s %-2s\n", dest, source, 
  939.                       pass, exportString, readFlag);
  940. a166 1
  941.         mountTable[index].pass = pass;
  942. a185 1
  943.         mountTable[index].pass = -1;
  944. d293 3
  945. a295 1
  946.     free(argTable);
  947. d328 1
  948. a328 1
  949.     Alloc(newPtr, ArgHeader, 1, "newPtr");
  950. d565 1
  951. a565 1
  952.     if ((mountTable[i].export == TRUE) && (mountTable[i].pass != 0) && 
  953. @
  954.  
  955.  
  956. 1.5
  957. log
  958. @cleaned a few things up
  959. @
  960. text
  961. @d17 1
  962. a17 1
  963. static char rcsid[] = "$Header: /sprite/src/admin/fsattach/RCS/misc.c,v 1.4 89/06/19 14:21:18 jhh Exp $ SPRITE (Berkeley)";
  964. d424 1
  965. d442 2
  966. a443 1
  967.     tempStream = fopen(rootTempOutputFile,"r+");
  968. d446 1
  969. a446 1
  970.                rootTempOutputFile);
  971. @
  972.  
  973.  
  974. 1.4
  975. log
  976. @Added stuff to preload prefix table
  977. @
  978. text
  979. @d17 1
  980. a17 1
  981. static char rcsid[] = "$Header: /sprite/src/admin/fsattach/RCS/misc.c,v 1.3 89/06/07 22:14:28 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  982. d431 1
  983. a431 1
  984.     (void) sprintf(outputFile, "%s.fsc", device);
  985. d559 2
  986. a560 1
  987.     if ((mountTable[i].export == TRUE) && (mountTable[i].pass != 0)) {
  988. d566 2
  989. a567 1
  990.         } else {
  991. @
  992.  
  993.  
  994. 1.3
  995. log
  996. @Spring cleaning - new mount table format, bug fixes
  997. @
  998. text
  999. @d17 1
  1000. a17 1
  1001. static char rcsid[] = "$Header: /sprite/src/admin/fsattach/RCS/misc.c,v 1.2 89/04/10 11:12:18 jhh Exp $ SPRITE (Berkeley)";
  1002. d184 2
  1003. d529 46
  1004. @
  1005.  
  1006.  
  1007. 1.2
  1008. log
  1009. @First working version
  1010. @
  1011. text
  1012. @d17 1
  1013. a17 1
  1014. static char rcsid[] = "$Header: /sprite/users/jhh/fsattach/RCS/misc.c,v 1.1 89/03/06 12:58:50 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  1015. a25 142
  1016.  * ParseConfig --
  1017.  *
  1018.  *    Parse the configuration file.
  1019.  *
  1020.  * Results:
  1021.  *    FAILURE if an error occured opening or parsing the file.
  1022.  *
  1023.  * Side effects:
  1024.  *    Global variables are set.
  1025.  *
  1026.  *----------------------------------------------------------------------
  1027.  */
  1028.  
  1029. ReturnStatus
  1030. ParseConfig(configFile)
  1031.     char    *configFile;        /* name of the configuration file */
  1032. {
  1033.     FILE         *stream;
  1034.     char        string[MAX_LINE_LENGTH];
  1035.     char        buffer[MAX_LINE_LENGTH];
  1036.     char        command[MAX_LINE_LENGTH];
  1037.     char        *eof;
  1038.     int            n;
  1039.     int            integer;
  1040.     int            line;
  1041.     ReturnStatus     returnStatus;
  1042.  
  1043.     returnStatus = SUCCESS;
  1044.     stream = fopen(configFile, "r");
  1045.     if (stream == (FILE *)NULL) {
  1046.     (void) fprintf(stderr, "%s: can't open \"%s\", ", progName, configFile);
  1047.     perror("");
  1048.     return FAILURE;
  1049.     }
  1050.     if (verbose) {
  1051.     fprintf(stderr,"Parsing configuration file %s.\n", configFile);
  1052.     }
  1053.     line = 0;
  1054.     for (eof = fgets(string, MAX_LINE_LENGTH, stream);
  1055.      eof != NULL;
  1056.      eof = fgets(string, MAX_LINE_LENGTH, stream)) {
  1057.  
  1058.     line++;
  1059.     n = sscanf(string, " %256s", command);
  1060.     if (n < 1 || *command == '#') {
  1061.         continue;
  1062.     }
  1063.     if (!strcmp("mountTableSize", command)) {
  1064.         n = sscanf(string, " %*s %d", &integer);
  1065.         if (n != 1) {
  1066.         (void) fprintf(stderr, "Garbled input at line %d: \"%d\"\n", 
  1067.             line, integer);
  1068.         returnStatus = FAILURE;
  1069.         goto exit;
  1070.         }
  1071.         if (integer < 0) {
  1072.         (void) fprintf(stderr, 
  1073.                    "Illegal mount table size at line %d: \"%d\"\n",
  1074.                    line, integer);
  1075.         returnStatus = FAILURE;
  1076.         goto exit;
  1077.         }
  1078.         mountTableSize = integer;
  1079.     } else if (!strcmp("rootTempOutputFile", command)) {
  1080.         n = sscanf(string, " %*s %256s", buffer);
  1081.         if (n != 1) {
  1082.         (void) fprintf(stderr, "Garbled input at line %d: \"%s\"\n", 
  1083.             line, buffer);
  1084.         returnStatus = FAILURE;
  1085.         goto exit;
  1086.         }
  1087.         Alloc(rootTempOutputFile, char, strlen(buffer) + 1, 
  1088.           "rootTempOutputFile");
  1089.         (void) strcpy(rootTempOutputFile, buffer);
  1090.     } else if (!strcmp("heapLimit", command)) {
  1091.         n = sscanf(string, " %*s %d", &integer);
  1092.         if (n != 1) {
  1093.         (void) fprintf(stderr, "Garbled input at line %d: \"%d\"\n", 
  1094.             line, integer);
  1095.         returnStatus = FAILURE;
  1096.         goto exit;
  1097.         }
  1098.         if (integer < 1) {
  1099.         (void) fprintf(stderr, "Illegal heapLimit at line %d: \"%d\"\n",
  1100.             line, integer);
  1101.         returnStatus = FAILURE;
  1102.         goto exit;
  1103.         }
  1104.         (void) sprintf(command, "%d", integer);
  1105.         Alloc(heapLimitString, char , strlen(command) + 1,
  1106.           "heapLimitString");
  1107.         (void) strcpy(heapLimitString, command);
  1108.     } else if (!strcmp("rootTempOutputFileSize", command)) {
  1109.         n = sscanf(string, " %*s %d", &integer);
  1110.         if (n != 1) {
  1111.         (void) fprintf(stderr, "Garbled input at line %d: \"%d\"\n", 
  1112.             line, integer);
  1113.         returnStatus = FAILURE;
  1114.         goto exit;
  1115.         }
  1116.         if (integer < 1) {
  1117.         (void) fprintf(stderr, 
  1118.                    "Illegal output file size at line %d: \"%d\"\n",
  1119.                    line, integer);
  1120.         returnStatus = FAILURE;
  1121.         goto exit;
  1122.         }
  1123.         rootTempOutputFileSize = integer;
  1124.     } else if (!strcmp("outputDir", command)) {
  1125.         n = sscanf(string, " %*s %256s", buffer);
  1126.         if (n != 1) {
  1127.         (void) fprintf(stderr, "Garbled input at line %d: \"%s\"\n", 
  1128.             line, buffer);
  1129.         returnStatus = FAILURE;
  1130.         goto exit;
  1131.         }
  1132.         Alloc(outputDir, char, strlen(buffer) +1,"outputDir");
  1133.         (void) strcpy(outputDir, buffer);
  1134.     } else if (!strcmp("fscheck", command)) {
  1135.         n = sscanf(string, " %*s %256s", buffer);
  1136.         if (n != 1) {
  1137.         (void) fprintf(stderr, "Garbled input at line %d: \"%s\"\n", 
  1138.             line, buffer);
  1139.         returnStatus = FAILURE;
  1140.         goto exit;
  1141.         }
  1142.         Alloc(fscheckPath, char, strlen(buffer) +1,"fscheckPath");
  1143.         (void) strcpy(fscheckPath, buffer);
  1144.     } else {
  1145.         (void) fprintf(stderr, "Garbled input at line %d: \"%s\"\n", 
  1146.             line, string);
  1147.     }
  1148.     }
  1149. exit:
  1150.     fclose(stream);
  1151.     return returnStatus;
  1152. }
  1153.  
  1154.  
  1155. /*
  1156.  *----------------------------------------------------------------------
  1157.  *
  1158. d28 2
  1159. a29 2
  1160.  *    Parses the mount information in the given string and fills in the
  1161.  *    next structure in the mount table.
  1162. d35 2
  1163. a36 1
  1164.  *    The next available entry in the mount table is filled in.
  1165. d43 2
  1166. a44 2
  1167.     char    *mountFile;
  1168.     int        *countPtr;
  1169. d51 1
  1170. d62 10
  1171. d73 1
  1172. d83 2
  1173. d98 6
  1174. a103 4
  1175.         (void) fprintf(stderr,
  1176.                "%s: Too many entries in mount file. Max is %d.\n",
  1177.                progName, mountTableSize);
  1178.         continue;
  1179. d105 1
  1180. a105 1
  1181.     if (!strcmp("Attach", command)) {
  1182. d115 1
  1183. a115 1
  1184.         if (!strcmp("export", exportString)) {
  1185. d117 1
  1186. a117 1
  1187.         } else if (!strcmp("local", exportString)) {
  1188. d149 1
  1189. a149 1
  1190.         if (!strcmp("r", readFlag)) {
  1191. d151 1
  1192. a151 1
  1193.         } else  if (!strcmp("rw", readFlag)) {
  1194. d168 5
  1195. a172 1
  1196.     } else if (!strcmp("Export", command)) {
  1197. d183 1
  1198. d186 85
  1199. d272 18
  1200. a289 7
  1201.         (void) fprintf(stderr, "Garbled input at line %d: \"%s\"\n", 
  1202.         line, string);
  1203.     }
  1204.     (void) strcpy(mountTable[index].source, source);
  1205.     (void) strcpy(mountTable[index].dest, dest);
  1206.     index++;
  1207.     }
  1208. d292 100
  1209. a391 1
  1210.     return SUCCESS;
  1211. d393 1
  1212. a421 1
  1213.     char    deviceName[MAX_FIELD_LENGTH];
  1214. d429 3
  1215. a431 9
  1216.     /*
  1217.      * Strip off all but the tail of the path.
  1218.      */
  1219.     (void) strcpy(deviceName, device);
  1220.     for(i = strlen(deviceName) - 1; i >= 0; i--) {
  1221.     if (deviceName[i] == '/') {
  1222.         i++;
  1223.         break;
  1224.     }
  1225. a432 5
  1226.     (void) sprintf(outputFile, "%s/%s.fsc", outputDir, deviceName);
  1227.     if (printOnly) {
  1228.     printf("Copying root output.\n");
  1229.     return;
  1230.     }
  1231. d439 1
  1232. a439 1
  1233.     tempStream = fopen(rootTempOutputFile,"rw");
  1234. d463 1
  1235. d469 6
  1236. a474 1
  1237.     (void) fwrite(buffer, sizeof(char), bytesToWrite, tempStream);
  1238. d503 1
  1239. a503 1
  1240.     "No Error",
  1241. d509 1
  1242. a509 1
  1243.     "No Error",
  1244. @
  1245.  
  1246.  
  1247. 1.1
  1248. log
  1249. @Initial revision
  1250. @
  1251. text
  1252. @d4 1
  1253. a4 1
  1254.  *    Description.
  1255. d17 1
  1256. a17 1
  1257. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/proto.c,v 1.2 89/01/07 04:12:18 rab Exp $ SPRITE (Berkeley)";
  1258. d31 1
  1259. a31 1
  1260.  *    None.
  1261. d41 1
  1262. a41 1
  1263.     char    *configFile;
  1264. d58 1
  1265. a58 1
  1266.     (void) exit(HARDERROR);
  1267. d144 10
  1268. d190 1
  1269. a190 1
  1270.     static char     tempbuf[MAX_FIELD_LENGTH];
  1271. a194 1
  1272.     Boolean         root;
  1273. d201 1
  1274. d207 1
  1275. a207 1
  1276.     (void) exit(HARDERROR);
  1277. d220 2
  1278. a221 2
  1279.     n = sscanf(string, " %256s", tempbuf);
  1280.     if (n < 1 || *tempbuf == '#') {
  1281. d230 9
  1282. a238 10
  1283.     n = sscanf(string, " %256s %256s %d %256s %256s", source, dest, &pass, 
  1284.            exportString, readFlag);
  1285.     if (n != 5) {
  1286.         (void) fprintf(stderr, "Garbled input at line %d: \"%s\"\n", 
  1287.                line, string);
  1288.         continue;
  1289.     }
  1290.     export = TRUE;
  1291.     root = FALSE;
  1292.     if (!strcmp("export", exportString)) {
  1293. d240 66
  1294. a305 4
  1295.     } else if (!strcmp("local", exportString)) {
  1296.         export = FALSE;
  1297.     } else if (!strcmp("root", exportString)) {
  1298.         root = TRUE;
  1299. d307 2
  1300. a308 15
  1301.         (void) fprintf(stderr, "Bad export value at line %d: \"%s\"\n", 
  1302.                line, exportString);
  1303.         continue;
  1304.     }
  1305.     if (pass < 0) {
  1306.         (void) fprintf(stderr, "Bad pass value at line %d: \"%d\"\n", 
  1307.                line, pass);
  1308.         continue;
  1309.     }
  1310.     if (pass > MAX_PASS) {
  1311.         (void) fprintf(stderr, 
  1312.                "Pass value %d too large at line %d: \"%d\"\n",
  1313.                line, pass);
  1314.         (void) fprintf(stderr, "Reset to %d.\n", MAX_PASS);
  1315.         pass = MAX_PASS;
  1316. a309 21
  1317.     if (pass == 0 && root != TRUE) {
  1318.         (void) fprintf(stderr, "Illegal pass value at line %d: %s.\n",
  1319.             line, "Only root can be checked on pass 0");
  1320.         continue;
  1321.     }
  1322.     if (pass > maxPass) {
  1323.         maxPass = pass;
  1324.     }
  1325.     if (!strcmp("r", readFlag)) {
  1326.         readonly = TRUE;
  1327.     } else  if (!strcmp("rw", readFlag)) {
  1328.         readonly = FALSE;
  1329.     } else {
  1330.         (void) fprintf(stderr, "Bad read/write value at line %d: \"%s\"\n",
  1331.                line, readFlag);
  1332.         continue;
  1333.     }
  1334.     if (verbose) {
  1335.         (void) printf("%-20s %-10s %2d %-10s %-2s\n", dest, source, pass, 
  1336.            exportString, readFlag);
  1337.     }
  1338. a311 4
  1339.     mountTable[index].pass = pass;
  1340.     mountTable[index].export = export;
  1341.     mountTable[index].root = root;
  1342.     mountTable[index].readonly = readonly;
  1343. d324 4
  1344. a327 2
  1345.  *    Does all the special stuff that need to be done to deal with
  1346.  *    the root output.
  1347. d333 1
  1348. a333 1
  1349.  *    The root output is appended to the output file and the temporary
  1350. d341 1
  1351. a341 1
  1352.     char        *device;
  1353. d346 1
  1354. d354 11
  1355. a364 1
  1356.     (void) sprintf(outputFile, "%s/%s.fsc", outputDir, device);
  1357. d429 2
  1358. a430 2
  1359.     int        code;
  1360.     MountInfo    *mountPtr;
  1361. d432 1
  1362. a432 1
  1363.     static char *softerrors[3] = {
  1364. d436 1
  1365. d438 1
  1366. a438 1
  1367.     static char *harderrors[7] = {
  1368. d447 1
  1369. d449 3
  1370. a451 2
  1371.     if (code < 0) {
  1372.     error = harderrors[-code];
  1373. d453 1
  1374. a453 1
  1375.     error = softerrors[code];
  1376. d456 1
  1377. a456 1
  1378.            mountPtr->device, code, error);
  1379. @
  1380.